
package xj.app;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
import javax.swing.*; 
import javax.imageio.*;

/**
 * Display an animated hourglass while a long task is being performed. 
 * All input will be blocked. 
 */
public class HourGlassPane 
  extends AnimationPane { 

  public HourGlassPane(JFrame frame) {
    super(frame);     

    blockInput();
    setBackground(Color.WHITE);
    //setFont(new Font("Default", Font.BOLD, 16));
    images = loadStripImageArray("process-working.png", 8, true);
  }

  public void start() {
    System.out.println("HourGlassPane.start()");
 
    if (frame != null) { 
      frame.setGlassPane(this); 
      setVisible(true);
      done = false;
      index = 0; 
      Thread runner = new Thread(new Runnable() {
	  public void run() { 
	    try { 
	      while (!done) { 
		repaint(); 
		index++;
		if (index >= images.length) {
		  index = 0; 
		}
		Thread.currentThread().sleep(100);
	      }
	    } catch (InterruptedException e) {}
	  }
	});
      runner.setPriority(Thread.MAX_PRIORITY);
      runner.start(); 
    }
  }

  public void stop() { 
    System.out.println("HourGlassPane.stop()");

    done = true; 
    setVisible(false); 
  }

  @Override
  public void paintComponent(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
			RenderingHints.VALUE_ANTIALIAS_ON);

    Rectangle clip = g.getClipBounds();
    AlphaComposite alpha = AlphaComposite.SrcOver.derive(0.65f);
    Composite composite = g2.getComposite();
    g2.setComposite(alpha);
    g2.setColor(getBackground());
    g2.fillRect(clip.x, clip.y, clip.width, clip.height);
    
    if (images != null && 
	index >= 0 && index < images.length) { 
      BufferedImage img = images[index];
      int w = img.getWidth();
      int h = img.getHeight();       
      g.drawImage(img, (clip.width - w) / 2, (clip.height - h) / 2, null);
    } 
  }

  BufferedImage[] images;
  int index = 0; 
  boolean done = true; 

  //
  //  Utilities to load image strip 
  //
  
  private GraphicsConfiguration gc = null;

  private static final String IMAGE_DIR = "/icons/";

  /* Load a strip file, <fnm>, holding <number> images. 
     Extract the individual images from the strip image file, <fnm>.
     We assume the images are stored in a single row, and that there
     are <number> of them. The images are returned as an array of
     BufferedImages
  */
  protected BufferedImage[] loadStripImageArray(String fnm, 
						int number, 
						boolean vertical) {
    if (gc == null) { 
      GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
      gc = ge.getDefaultScreenDevice().getDefaultConfiguration();
    }

    if (number <= 0) {
      return null;
    }

    BufferedImage stripIm = null;
    try { 
      stripIm = ImageIO.read(getClass().getResource(IMAGE_DIR + fnm)); 
    } catch (IOException e) {     
      e.printStackTrace();
    }
     
    if (stripIm == null) {
      System.out.println("Returning null");
      return null;
    }
    
    int width = stripIm.getWidth();
    int height = stripIm.getHeight();
    if (vertical) { 
      height /= number;
    } else {  
      width /= number; 
    }
    
    int transparency = stripIm.getColorModel().getTransparency();
    
    BufferedImage[] strip = new BufferedImage[number];
    Graphics2D stripGC;
    
    // each BufferedImage from the strip file is stored in strip[]
    for (int i = 0; i < number; i++) {
      strip[i] = gc.createCompatibleImage(width, height, transparency);
      
      // create a graphics context
      stripGC = strip[i].createGraphics();
      // stripGC.setComposite(AlphaComposite.Src);
      
      // copy image
      if (vertical) { 
	stripGC.drawImage(stripIm, 
			  0, 0, width, height,
			  0, i * height, width, i * height + height, 
			  null);
      } else { 
	stripGC.drawImage(stripIm, 
			  0, 0, width, height,
			  i * width,0, (i * width) + width, height,
			  null);
      }
      stripGC.dispose();
    } 
    return strip;
  } 

}